#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <stdint.h>
#include <math.h>
#include <errno.h>
#include <string.h>

// TSL2561寄存器地址 (带命令位)
#define TSL2561_CMD           0x80
#define TSL2561_REG_CONTROL   0x00
#define TSL2561_REG_TIMING    0x01
#define TSL2561_REG_ID        0x0A
#define TSL2561_REG_DATA0LOW  0x0C
#define TSL2561_REG_DATA0HIGH 0x0D
#define TSL2561_REG_DATA1LOW  0x0E
#define TSL2561_REG_DATA1HIGH 0x0F

// 增益设置
#define TSL2561_GAIN_1X       0x00
#define TSL2561_GAIN_16X      0x10

// 积分时间设置
#define TSL2561_INTEG_13MS    0x00
#define TSL2561_INTEG_101MS   0x01
#define TSL2561_INTEG_402MS   0x02

// 默认I2C地址
#define TSL2561_ADDR          0x39

// 全局变量
static int i2c_fd = -1;
static uint8_t current_gain = TSL2561_GAIN_1X;
static uint8_t current_integ = TSL2561_INTEG_402MS;

#include "get_tsl.h"


/**
 * @brief 初始化TSL2561光照传感器
 * @return 0成功，-1失败
 */
int tsl2561_init(const char *i2c_device) {
	// 打开I2C设备
	i2c_fd = open(i2c_device, O_RDWR);
	if (i2c_fd < 0) {
		fprintf(stderr, "无法打开I2C设备 %s: %s\n", i2c_device, strerror(errno));
		return -1;
	}

	// 设置I2C地址
	if (ioctl(i2c_fd, I2C_SLAVE, TSL2561_ADDR) < 0) {
		fprintf(stderr, "无法设置I2C地址 0x%02X: %s\n", TSL2561_ADDR, strerror(errno));
		close(i2c_fd);
		i2c_fd = -1;
		return -1;
	}

	// 读取设备ID（可选，用于验证设备）
	uint8_t id_reg = TSL2561_REG_ID | TSL2561_CMD;
	uint8_t device_id = 0;

	if (write(i2c_fd, &id_reg, 1) != 1) {
		fprintf(stderr, "写入ID寄存器地址失败: %s\n", strerror(errno));
	} else if (read(i2c_fd, &device_id, 1) != 1) {
		fprintf(stderr, "读取设备ID失败: %s\n", strerror(errno));
	} else {
		// 支持多种设备ID (0x10, 0x50等)
		if (device_id != 0x10 && device_id != 0x50) {
			fprintf(stderr, "警告: 无效设备ID: 0x%02X\n", device_id);
		}
	}

	// 设置默认增益和积分时间
	if (tsl2561_set_timing(current_gain, current_integ) != 0) {
		fprintf(stderr, "设置时序失败\n");
		tsl2561_close();
		return -1;
	}

	// 启用传感器
	if (tsl2561_enable() != 0) {
		fprintf(stderr, "启用传感器失败\n");
		tsl2561_close();
		return -1;
	}

	// 等待首次转换完成
	usleep(410000); // 402ms + 余量

	return 0;
}

/**
 * @brief 关闭TSL2561传感器
 */
void tsl2561_close(void) {
	if (i2c_fd >= 0) {
		tsl2561_disable();
		close(i2c_fd);
		i2c_fd = -1;
	}
}

/*
 * @brief 设置增益和积分时间
 * @param gain 增益设置 (TSL2561_GAIN_1X 或 TSL2561_GAIN_16X)
 * @param integ_time 积分时间 (TSL2561_INTEG_13MS, TSL2561_INTEG_101MS, TSL2561_INTEG_402MS)
 * @return 0成功，-1失败
 */
int tsl2561_set_timing(uint8_t gain, uint8_t integ_time) {
	if (i2c_fd < 0) return -1;

	uint8_t timing_reg = TSL2561_REG_TIMING | TSL2561_CMD;
	uint8_t timing_value = gain | integ_time;

	uint8_t buffer[2] = {timing_reg, timing_value};

	if (write(i2c_fd, buffer, sizeof(buffer)) != sizeof(buffer)) {
		fprintf(stderr, "写入时序寄存器失败: %s\n", strerror(errno));
		return -1;
	}

	current_gain = gain;
	current_integ = integ_time;

	return 0;
}

/**
 * @brief 启用传感器
 * @return 0成功，-1失败
 */
int tsl2561_enable(void) {
	if (i2c_fd < 0) return -1;

	uint8_t control_reg = TSL2561_REG_CONTROL | TSL2561_CMD;
	uint8_t power_on = 0x03; // 开启电源和ADC

	uint8_t buffer[2] = {control_reg, power_on};

	if (write(i2c_fd, buffer, sizeof(buffer)) != sizeof(buffer)) {
		fprintf(stderr, "启用传感器失败: %s\n", strerror(errno));
		return -1;
	}

	return 0;
}

/**
 * @brief 禁用传感器
 * @return 0成功，-1失败
 */
int tsl2561_disable(void) {
	if (i2c_fd < 0) return -1;

	uint8_t control_reg = TSL2561_REG_CONTROL | TSL2561_CMD;
	uint8_t power_off = 0x00; // 关闭电源

	uint8_t buffer[2] = {control_reg, power_off};

	if (write(i2c_fd, buffer, sizeof(buffer)) != sizeof(buffer)) {
		fprintf(stderr, "禁用传感器失败: %s\n", strerror(errno));
		return -1;
	}

	return 0;
}

/**
 * @brief 读取光强数据
 * @param ch0 通道0值（可见光+红外）
 * @param ch1 通道1值（仅红外）
 * @return 0成功，-1失败
 */
int tsl2561_read_data(uint16_t *ch0, uint16_t *ch1) {
	if (i2c_fd < 0) return -1;

	uint8_t data0_low_reg = TSL2561_REG_DATA0LOW | TSL2561_CMD;
	uint8_t data0_high_reg = TSL2561_REG_DATA0HIGH | TSL2561_CMD;
	uint8_t data1_low_reg = TSL2561_REG_DATA1LOW | TSL2561_CMD;
	uint8_t data1_high_reg = TSL2561_REG_DATA1HIGH | TSL2561_CMD;

	uint8_t ch0_low, ch0_high, ch1_low, ch1_high;

	// 读取通道0低字节
	if (write(i2c_fd, &data0_low_reg, 1) != 1 ||
			read(i2c_fd, &ch0_low, 1) != 1) {
		return -1;
	}

	// 读取通道0高字节
	if (write(i2c_fd, &data0_high_reg, 1) != 1 ||
			read(i2c_fd, &ch0_high, 1) != 1) {
		return -1;
	}

	// 读取通道1低字节
	if (write(i2c_fd, &data1_low_reg, 1) != 1 ||
			read(i2c_fd, &ch1_low, 1) != 1) {
		return -1;
	}

	// 读取通道1高字节
	if (write(i2c_fd, &data1_high_reg, 1) != 1 ||
			read(i2c_fd, &ch1_high, 1) != 1) {
		return -1;
	}

	// 组合16位值
	*ch0 = (ch0_high << 8) | ch0_low;
	*ch1 = (ch1_high << 8) | ch1_low;

	return 0;
}

/**
 * @brief 计算光照强度（Lux）
 * @param ch0 通道0值
 * @param ch1 通道1值
 * @return 光照强度值（Lux），出错返回-1.0
 */
float tsl2561_calculate_lux(uint16_t ch0, uint16_t ch1) {
	// 避免除以零
	if (ch0 == 0) {
		return 0.0;
	}

	// 根据增益和积分时间计算比例因子
	float gain_factor = (current_gain == TSL2561_GAIN_1X) ? 1.0f : 0.0625f;
	float integ_factor = 0.0f;

	switch (current_integ) {
		case TSL2561_INTEG_13MS:
			integ_factor = 0.034f;
			break;
		case TSL2561_INTEG_101MS:
			integ_factor = 0.252f;
			break;
		case TSL2561_INTEG_402MS:
		default:
			integ_factor = 1.0f;
			break;
	}

	// 应用比例因子
	float ch0_scaled = (float)ch0 * gain_factor / integ_factor;
	float ch1_scaled = (float)ch1 * gain_factor / integ_factor;

	// 计算比率
	float ratio = ch1_scaled / ch0_scaled;

	// 根据比率选择适当的计算系数
	float lux = 0.0;

	if (ratio <= 0.50) {
		lux = (0.0304 * ch0_scaled) - (0.062 * ch0_scaled * powf(ratio, 1.4));
	} else if (ratio <= 0.61) {
		lux = (0.0224 * ch0_scaled) - (0.031 * ch1_scaled);
	} else if (ratio <= 0.80) {
		lux = (0.0128 * ch0_scaled) - (0.0153 * ch1_scaled);
	} else if (ratio <= 1.30) {
		lux = (0.00146 * ch0_scaled) - (0.00112 * ch1_scaled);
	} else {
		lux = 0.0; // 无效比率
	}

	return lux;
}
/**
 * @brief 获取当前光照强度
 * @return 光照强度值（Lux），出错返回-1.0
 */
int get_illuminance(float *lux) {
	static int initialized = 0;

	// 延迟时间（根据积分时间确定）
	unsigned int delay_us = 0;
	switch (current_integ) {
		case TSL2561_INTEG_13MS: delay_us = 20000; break;   // 13ms + 余量
		case TSL2561_INTEG_101MS: delay_us = 110000; break; // 101ms + 余量
		case TSL2561_INTEG_402MS: delay_us = 410000; break; // 402ms + 余量
		default: delay_us = 410000;
	}

	// 初始化传感器（如果尚未初始化）
	if (!initialized) {
		if (tsl2561_init("/dev/i2c-1") != 0) {
			fprintf(stderr, "TSL2561初始化失败\n");
			return -1.0;
		}
		initialized = 1;
	}

	// 等待转换完成
	usleep(delay_us);

	// 读取数据
	uint16_t ch0, ch1;
	if (tsl2561_read_data(&ch0, &ch1) != 0) {
		fprintf(stderr, "读取传感器数据失败\n");
		return -1.0;
	}

	// 计算光照强度
	*lux = tsl2561_calculate_lux(ch0, ch1);
	dbg_printf("illuminance:%.4f\n", *lux);
	return 0;
}

/**
 *  * @brief 清理资源
 *   */
void cleanup_tsl2561(void) {
	tsl2561_close();
}
